//=============================================================================
// filename: main.cpp
// description: the main entry point for everything
// author: Jay Tomten (jaytomten@gmail.com)
//=============================================================================

#include <GL/glu.h>
#include <SDL/SDL.h>
#include <iostream>
#include "game.h"
#include "level.h"
#include "story.h"
#include "player.h"

Game gEngine;                                                                   // our game class
Player p1;                                                                      // the main player
Player p2;                                                                      // secondary or AI player

//=============================================================================
// Load() - load a level/state
bool Load(int type, int level)
    {

    cout << "\n======== START LEVEL LOADING  ========\n";
    bool alive = true;
    gEngine.stateTimer = 0.0f;
    //
    // load main menu state
    //
    if  (type == GAME_MAIN_MENU)
        {
        cout << "Loading from state " << gEngine.state << " to main menu...\n";
        gEngine.state = GAME_MAIN_MENU;
        gEngine.reload = false;
        glViewport(0, 0, gEngine.gScreen.width, gEngine.gScreen.height);

        gEngine.gList = new List();
        p1.pList = new List();
        p2.pList = new List();

        if  (!p1.Init(&gEngine, PLAYER_1, &p2)
        ||   !p2.Init(&gEngine, PLAYER_0, &p1))
            {
            return false;
            }
        if  (!gEngine.gLevel.Init(level, gEngine.gList, p1.pList, p2.pList, gEngine.gScreen.smooth))
            {
            alive = false;
            }
        p1.pCamera.GoTo(99.0, 0.0, 0.0);
        p1.pCamera.demo = true;
        cout << "Main menu loading... success.\n";
        }
    //
    // load story state
    //
    else if(type == GAME_STORY)
        {
        cout << "Loading from state " << gEngine.state << " to story...\n";
        gEngine.state = GAME_STORY;
        gEngine.reload = false;
        glViewport(0, 0, gEngine.gScreen.width, gEngine.gScreen.height);

        delete gEngine.gList;
        delete p1.pList;
        delete p2.pList;

        gEngine.gList = new List();
        p1.pList = new List();
        p2.pList = new List();

        if  (!p1.Init(&gEngine, PLAYER_1, &p2)
        ||   !p2.Init(&gEngine, PLAYER_0, &p1))
            {
            return false;
            }
        if  (!gEngine.gLevel.Init(level, gEngine.gList, p1.pList, p2.pList, gEngine.gScreen.smooth))
            {
            alive = false;
            }
        p1.pCamera.GoTo(-90.0, 0.0, 60.0);
        p1.pCamera.story = true;
        cout << "Story loading... success.\n";
        }
    //
    // load single play state
    //
    else if(type == GAME_SINGLE_PLAYER)
        {
        cout << "Loading from state " << gEngine.state << " to single player...\n";
        gEngine.state = GAME_SINGLE_PLAYER;
        gEngine.reload = false;
        glViewport(0, 0, gEngine.gScreen.width, gEngine.gScreen.height);

        delete gEngine.gList;
        delete p1.pList;
        delete p2.pList;

        gEngine.gList = new List();
        p1.pList = new List();
        p2.pList = new List();

        if  (!p1.Init(&gEngine, PLAYER_1, &p2)
        ||   !p2.Init(&gEngine, PLAYER_0, &p1))
            {
            alive = false;
            }
        if  (!gEngine.gLevel.Init(level, gEngine.gList, p1.pList, p2.pList, gEngine.gScreen.smooth))
            {
            alive = false;
            }
        p1.pCamera.GoTo(-99.0, 0.0, 0.0);
        cout << "Level " << level << " loading... success.\n";
        }
    //
    // load multi player state
    //
    else if (type == GAME_MULTI_PLAYER_LOCAL)
        {
        cout << "Loading from state " << gEngine.state << " to multiplayer...\n";
        gEngine.state = GAME_MULTI_PLAYER_LOCAL;
        gEngine.reload = false;

        glViewport(0, 0, gEngine.gScreen.width, gEngine.gScreen.height);

        gEngine.gList = new List();
        p1.pList = new List();
        p2.pList = new List();

        if  (!p1.Init(&gEngine, PLAYER_1, &p2)
        ||   !p2.Init(&gEngine, PLAYER_2, &p1))
            {
            alive = false;
            }
        if  (!gEngine.gLevel.Init(level, gEngine.gList, p1.pList, p2.pList, gEngine.gScreen.smooth))
            {
            alive = false;
            }
        p1.pCamera.GoTo(-99.0, 0.0, 0.0);
        p2.pCamera.GoTo(99.0, 0.0, 0.0);
        cout << "Multiplayer level " << level << " loading... success.\n";
        }
    cout << "======== END LEVEL LOADING    ========\n";
    return alive;
    }

//=============================================================================
// CheckState() - check the game state
bool CheckState()
    {
    bool alive = true;
    if  (gEngine.reload == true)                                                // load the next state if called for
        {
        Load(gEngine.state, gEngine.nextLevel);
        }
    else
        {
        switch (gEngine.state)
            {
        case GAME_CLOSING:
            gEngine.stateTimer += gEngine.gTime.GetDelta();
            if  (gEngine.stateTimer > 5.0f)
                {
                alive = false;
                gEngine.stateTimer = 0.0f;
                }
            break;

        case GAME_LOADING:
            gEngine.stateTimer += gEngine.gTime.GetDelta();
            if  (gEngine.stateTimer > 5.0f)
                {
                gEngine.state = GAME_MAIN_MENU;
                gEngine.stateTimer = 0.0f;
                }
            break;

        case GAME_STORY:
            if  (gEngine.stateTimer > 5.0f)
                {
                gEngine.stateTimer = 0.0f;
                alive = Load(GAME_SINGLE_PLAYER, gEngine.gLevel.level + 1);
                }
            else
                {
                gEngine.stateTimer += gEngine.gTime.GetDelta();
                }
            break;

        case GAME_SINGLE_PLAYER:
            if  (p2.pStats.fobs < 1)
                {
                if (gEngine.gLevel.level == LEVEL_8)
                    {
                    gEngine.state = GAME_SINGLE_TOTAL_VICTORY;
                    }
                else
                    {
                    gEngine.state = GAME_SINGLE_WIN;
                    }
                }
            else if (p1.pStats.fobs < 1)
                {
                gEngine.state = GAME_SINGLE_LOSE;
                }
            break;

        case GAME_MULTI_PLAYER_LOCAL:
            if  (p2.pStats.fobs == 0)
                {
                gEngine.state = GAME_MULTI_LOCAL_P1_WIN;
                }
            else if(p1.pStats.fobs == 0)
                {
                gEngine.state = GAME_MULTI_LOCAL_P2_WIN;
                }
            break;

        case GAME_SINGLE_TOTAL_VICTORY:
        case GAME_SINGLE_WIN:
            if  (gEngine.stateTimer > 5.0f)
                {
                cout << "Single player winner!\n";
                gEngine.stateTimer = 0.0f;
                if  (gEngine.gLevel.level != LEVEL_8)
                    {
                    int level = gEngine.gLevel.level + 1;
                    alive = Load(GAME_STORY, level);
                    gEngine.nextLevel = level;
                    }
                else
                    {
                    alive = Load(GAME_MAIN_MENU, LEVEL_DEMO);
                    }
                }
            else
                {
                gEngine.stateTimer += gEngine.gTime.GetDelta();
                }
            break;

        case GAME_SINGLE_LOSE:
            if  (gEngine.stateTimer > 5.0f)
                {
                gEngine.stateTimer = 0.0f;
                cout << "Single player loser!\n";
                alive = Load(GAME_MAIN_MENU, LEVEL_DEMO);
                }
            else
                {
                gEngine.stateTimer += gEngine.gTime.GetDelta();
                }
            break;

        case GAME_MULTI_LOCAL_P1_WIN:
            if  (gEngine.stateTimer > 5.0f)
                {
                gEngine.stateTimer = 0.0f;
                cout << "P1 is a  Loser!\n";
                alive = Load(GAME_MAIN_MENU, LEVEL_DEMO);
                }
            else
                {
                gEngine.stateTimer += gEngine.gTime.GetDelta();
                }
            break;

        case GAME_MULTI_LOCAL_P2_WIN:
            if  (gEngine.stateTimer > 5.0f)
                {
                gEngine.stateTimer = 0.0f;
                cout << "P1 is a  Loser!\n";
                alive = Load(GAME_MAIN_MENU, LEVEL_DEMO);
                }
            else
                {
                gEngine.stateTimer += gEngine.gTime.GetDelta();
                }
            break;

        case GAME_MAIN_MENU:
        case GAME_LEVEL_MENU:
        default:
            break;
            }
        }
    return alive;
    }

//=============================================================================
// main() - our starting point
int main(int argc, char *argv[])
    {
    //
    // process command line arguments
    //
    if  (argc > 0)
        {
        argv = NULL;
        }
    //
    // inital game loading
    //
    bool alive = true;
    if  (gEngine.Init())
        {
        alive = Load(GAME_MAIN_MENU, LEVEL_DEMO);
        gEngine.state = GAME_LOADING;
        gEngine.stateTimer = 0.0f;
        }
    //
    // main game loop
    //
    while (alive)
        {
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        glLoadIdentity();
        glFlush();
        //
        // single player screens
        //
        if (gEngine.state != GAME_MULTI_PLAYER_LOCAL
        &&  gEngine.state != GAME_MULTI_LOCAL_P2_WIN
        &&  gEngine.state != GAME_MULTI_LOCAL_P1_WIN)
            {
            alive = gEngine.Update(gEngine.gTime.GetDelta());
            alive = p2.Update(gEngine.gTime.GetDelta());
            alive = p1.Update(gEngine.gTime.GetDelta());
            gEngine.Draw();
            p2.Draw();
            p1.Draw();
            }
        //
        // split screen style
        //
        else
            {
            alive = gEngine.Update(gEngine.gTime.GetDelta());
            alive = p1.Update(gEngine.gTime.GetDelta());                        // player 1
            gEngine.Draw();
            p2.Draw();
            p1.Draw();
            alive = p2.Update(gEngine.gTime.GetDelta());                        // player 2 updates are slightly later that player 1
            gEngine.Draw();
            p1.Draw();
            p2.Draw();
            }
        alive = CheckState();                                                   // check the state and start over from the begining if alive
        SDL_GL_SwapBuffers();                                                   // flip the screen
        }
    gEngine.Exit();                                                             // clean up
    return 0;
    }
